﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;

namespace Gumini.JulaDB.Provider
{
    public class JulaDbParameterCollection : DbParameterCollection
    {
        private readonly List<JulaDbParameter> _parameters = new List<JulaDbParameter>();

        /// <summary>
        /// Adds a <see cref="T:System.Data.Common.DbParameter"/> item with the specified value to the <see cref="T:System.Data.Common.DbParameterCollection"/>.
        /// </summary>
        /// <param name="value">The <see cref="P:System.Data.Common.DbParameter.Value"/> of the <see cref="T:System.Data.Common.DbParameter"/> to add to the collection.</param>
        /// <returns>
        /// The index of the <see cref="T:System.Data.Common.DbParameter"/> object in the collection.
        /// </returns>
        public override int Add(object value)
        {
            _parameters.Add((JulaDbParameter)value);
            return _parameters.Count - 1;
        }

        /// <summary>
        /// Adds an array of items with the specified values to the <see cref="T:System.Data.Common.DbParameterCollection"/>.
        /// </summary>
        /// <param name="values">An array of values of type <see cref="T:System.Data.Common.DbParameter"/> to add to the collection.</param>
        public override void AddRange(Array values)
        {
            _parameters.AddRange(values.Cast<JulaDbParameter>());
        }

        /// <summary>
        /// Removes all <see cref="T:System.Data.Common.DbParameter"/> values from the <see cref="T:System.Data.Common.DbParameterCollection"/>.
        /// </summary>
        public override void Clear()
        {
            _parameters.Clear();
        }

        /// <summary>
        /// Indicates whether a <see cref="T:System.Data.Common.DbParameter"/> with the specified name exists in the collection.
        /// </summary>
        /// <param name="parameterName">The name of the <see cref="T:System.Data.Common.DbParameter"/> to look for in the collection.</param>
        /// <returns>
        /// true if the <see cref="T:System.Data.Common.DbParameter"/> is in the collection; otherwise false.
        /// </returns>
        public override bool Contains(string parameterName)
        {
            return IndexOf(parameterName) != -1;
        }

        /// <summary>
        /// Indicates whether a <see cref="T:System.Data.Common.DbParameter"/> with the specified <see cref="P:System.Data.Common.DbParameter.Value"/> is contained in the collection.
        /// </summary>
        /// <param name="value">The <see cref="P:System.Data.Common.DbParameter.Value"/> of the <see cref="T:System.Data.Common.DbParameter"/> to look for in the collection.</param>
        /// <returns>
        /// true if the <see cref="T:System.Data.Common.DbParameter"/> is in the collection; otherwise false.
        /// </returns>
        public override bool Contains(object value)
        {
            return _parameters.Contains((JulaDbParameter)value);
        }

        /// <summary>
        /// This method is not supported.
        /// </summary>
        public override void CopyTo(Array array, int index)
        {
            throw new NotSupportedException("CopyTo() is not supported");
        }

        /// <summary>
        /// Specifies the number of items in the collection.
        /// </summary>
        /// <returns>The number of items in the collection.</returns>
        public override int Count
        {
            get { return _parameters.Count; }
        }

        /// <summary>
        /// Exposes the <see cref="M:System.Collections.IEnumerable.GetEnumerator"/> method, which supports a simple iteration over a collection by a .NET Framework data provider.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through the collection.
        /// </returns>
        public override IEnumerator GetEnumerator()
        {
            return _parameters.GetEnumerator();
        }

        /// <summary>
        /// Returns <see cref="T:System.Data.Common.DbParameter"/> the object with the specified name.
        /// </summary>
        /// <param name="parameterName">The name of the <see cref="T:System.Data.Common.DbParameter"/> in the collection.</param>
        /// <returns>
        /// The <see cref="T:System.Data.Common.DbParameter"/> the object with the specified name.
        /// </returns>
        protected override DbParameter GetParameter(string parameterName)
        {
            return _parameters[IndexOf(parameterName)];
        }

        /// <summary>
        /// Returns the <see cref="T:System.Data.Common.DbParameter"/> object at the specified index in the collection.
        /// </summary>
        /// <param name="index">The index of the <see cref="T:System.Data.Common.DbParameter"/> in the collection.</param>
        /// <returns>
        /// The <see cref="T:System.Data.Common.DbParameter"/> object at the specified index in the collection.
        /// </returns>
        protected override DbParameter GetParameter(int index)
        {
            return _parameters[index];
        }

        /// <summary>
        /// Returns the index of the <see cref="T:System.Data.Common.DbParameter"/> object with the specified name.
        /// </summary>
        /// <param name="parameterName">The name of the <see cref="T:System.Data.Common.DbParameter"/> object in the collection.</param>
        /// <returns>
        /// The index of the <see cref="T:System.Data.Common.DbParameter"/> object with the specified name.
        /// </returns>
        public override int IndexOf(string parameterName)
        {
            var parameter = _parameters.
                Where(p => String.Compare(p.ParameterName, parameterName, true) == 0).First();
            return _parameters.IndexOf(parameter);
        }

        /// <summary>
        /// Returns the index of the specified <see cref="T:System.Data.Common.DbParameter"/> object.
        /// </summary>
        /// <param name="value">The <see cref="T:System.Data.Common.DbParameter"/> object in the collection.</param>
        /// <returns>
        /// The index of the specified <see cref="T:System.Data.Common.DbParameter"/> object.
        /// </returns>
        public override int IndexOf(object value)
        {
            return _parameters.IndexOf((JulaDbParameter)value);
        }

        /// <summary>
        /// Inserts the specified index of the <see cref="T:System.Data.Common.DbParameter"/> object with the specified name into the collection at the specified index.
        /// </summary>
        /// <param name="index">The index at which to insert the <see cref="T:System.Data.Common.DbParameter"/> object.</param>
        /// <param name="value">The <see cref="T:System.Data.Common.DbParameter"/> object to insert into the collection.</param>
        public override void Insert(int index, object value)
        {
            _parameters.Insert(index, (JulaDbParameter)value);
        }

        /// <summary>
        /// Removes the specified <see cref="T:System.Data.Common.DbParameter"/> object from the collection.
        /// </summary>
        /// <param name="value">The <see cref="T:System.Data.Common.DbParameter"/> object to remove.</param>
        public override void Remove(object value)
        {
            _parameters.Remove((JulaDbParameter)value);
        }

        /// <summary>
        /// Removes the <see cref="T:System.Data.Common.DbParameter"/> object with the specified name from the collection.
        /// </summary>
        /// <param name="parameterName">The name of the <see cref="T:System.Data.Common.DbParameter"/> object to remove.</param>
        public override void RemoveAt(string parameterName)
        {
            RemoveAt(IndexOf(parameterName));
        }

        /// <summary>
        /// Removes the <see cref="T:System.Data.Common.DbParameter"/> object at the specified from the collection.
        /// </summary>
        /// <param name="index">The index where the <see cref="T:System.Data.Common.DbParameter"/> object is located.</param>
        public override void RemoveAt(int index)
        {
            _parameters.RemoveAt(index);
        }

        /// <summary>
        /// Sets the <see cref="T:System.Data.Common.DbParameter"/> object with the specified name to a new value.
        /// </summary>
        /// <param name="parameterName">The name of the <see cref="T:System.Data.Common.DbParameter"/> object in the collection.</param>
        /// <param name="value">The new <see cref="T:System.Data.Common.DbParameter"/> value.</param>
        protected override void SetParameter(string parameterName, DbParameter value)
        {
            SetParameter(IndexOf(parameterName), value);
        }

        /// <summary>
        /// Sets the <see cref="T:System.Data.Common.DbParameter"/> object at the specified index to a new value.
        /// </summary>
        /// <param name="index">The index where the <see cref="T:System.Data.Common.DbParameter"/> object is located.</param>
        /// <param name="value">The new <see cref="T:System.Data.Common.DbParameter"/> value.</param>
        protected override void SetParameter(int index, DbParameter value)
        {
            _parameters[index] = (JulaDbParameter)value;
        }

        /// <summary>
        /// Always returns false.
        /// </summary>
        public override bool IsFixedSize
        {
            get { return false; }
        }

        /// <summary>
        /// Always returns false.
        /// </summary>
        public override bool IsReadOnly
        {
            get { return false; }
        }

        /// <summary>
        /// Always returns true.
        /// </summary>
        public override bool IsSynchronized
        {
            get { return true; }
        }

        /// <summary>
        /// Returns null.
        /// </summary>
        public override object SyncRoot
        {
            get { return null; }
        }
    }
}
